package service

import (
	"context"
	v1 "gin-vben-admin/api/v1"
	"gin-vben-admin/api/v1/errcode"
	"gin-vben-admin/internal/model"
	"gin-vben-admin/internal/repository"
	"github.com/opdss/go-helper/slices"
)

type SysRoleService interface {
	GetPageList(ctx context.Context, req *v1.SysRoleListReq) (total int64, list []*model.SysRole, err error)
	Create(ctx context.Context, req *v1.SysRoleCreateReq) error
	Update(ctx context.Context, req *v1.SysRoleUpdateReq) error
	Delete(ctx context.Context, roleId int64) error
}

func NewSysRoleService(service *Service, roleRepo repository.SysRoleRepository, menuRepo repository.SysMenuRepository) SysRoleService {
	return &sysRoleService{
		roleRepo: roleRepo,
		menuRepo: menuRepo,
		Service:  service,
	}
}

type sysRoleService struct {
	roleRepo repository.SysRoleRepository
	menuRepo repository.SysMenuRepository
	*Service
}

// GetPageList 角色列表
func (s *sysRoleService) GetPageList(ctx context.Context, req *v1.SysRoleListReq) (total int64, list []*model.SysRole, err error) {
	total, list, err = s.roleRepo.PageList(ctx, req, "Menus")
	if err != nil {
		return
	}
	for i := range list {
		list[i].SetMenuIds()
	}
	return
}

func (s *sysRoleService) Create(ctx context.Context, req *v1.SysRoleCreateReq) error {
	m := model.SysRole{
		RoleName: req.RoleName,
		Sort:     req.Sort,
		Status:   req.Status,
		Remark:   req.Remark,
		CreateBy: req.AuthId,
		UpdateBy: req.AuthId,
	}
	//检查下绑定的菜单操作
	menuIds := slices.Unique(req.MenuIds)
	if len(menuIds) != len(req.MenuIds) {
		return errcode.ErrBadRequest.New("绑定的菜单操作不合法")
	}
	//检查menuid的合法性
	menuModels, err := s.menuRepo.GetMenuActionByIds(ctx, menuIds)
	if err != nil {
		return err
	}
	if len(menuModels) != len(req.MenuIds) {
		return errcode.ErrBadRequest.New("绑定的菜单操作不合法")
	}

	return s.tm.Transaction(ctx, func(ctx context.Context) error {
		err := s.roleRepo.Create(ctx, &m)
		if err != nil {
			return err
		}
		if len(menuIds) > 0 {
			roleMenus := make([]model.SysRoleMenu, len(menuIds))
			permissions := make([]*model.SysPermission, 0)
			for i, mm := range menuModels {
				roleMenus[i] = model.SysRoleMenu{
					RoleId: m.RoleId,
					MenuId: mm.MenuId,
				}
				for _, api := range mm.Apis {
					permissions = append(permissions, &model.SysPermission{
						RoleId: m.RoleId,
						MenuId: mm.MenuId,
						ApiKey: api.Key,
						Status: m.Status,
					})
				}
			}
			if err = s.roleRepo.CreateRoleMenus(ctx, roleMenus); err != nil {
				return err
			}
			if len(permissions) > 0 {
				return s.roleRepo.CreatePermissions(ctx, permissions)
			}
			return nil
		}
		return nil
	})
}

// Update 更新角色
func (s *sysRoleService) Update(ctx context.Context, req *v1.SysRoleUpdateReq) error {
	m, err := s.roleRepo.GetById(ctx, req.RoleId)
	if err != nil {
		return err
	}
	m.RoleName = req.RoleName
	m.Sort = req.Sort
	m.Status = req.Status
	m.Remark = req.Remark
	m.UpdateBy = req.AuthId

	//检查下绑定的菜单操作
	menuIds := slices.Unique(req.MenuIds)
	if len(menuIds) != len(req.MenuIds) {
		return errcode.ErrBadRequest.New("绑定的菜单操作不合法")
	}
	//检查menuid的合法性
	menuModels, err := s.menuRepo.GetMenuActionByIds(ctx, menuIds)
	if err != nil {
		return err
	}
	if len(menuModels) != len(req.MenuIds) {
		return errcode.ErrBadRequest.New("绑定的菜单操作不合法")
	}

	return s.tm.Transaction(ctx, func(ctx context.Context) error {
		if err = s.roleRepo.Update(ctx, m); err != nil {
			return err
		}
		if err = s.roleRepo.DeleteRoleMenuByRoleId(ctx, m.RoleId); err != nil {
			return err
		}
		if err = s.roleRepo.DeletePermissionByRoleId(ctx, m.RoleId); err != nil {
			return err
		}
		if len(menuModels) > 0 {
			roleMenus := make([]model.SysRoleMenu, len(menuModels))
			permissions := make([]*model.SysPermission, 0)
			for i, mm := range menuModels {
				roleMenus[i] = model.SysRoleMenu{
					RoleId: m.RoleId,
					MenuId: mm.MenuId,
				}
				for _, api := range mm.Apis {
					permissions = append(permissions, &model.SysPermission{
						RoleId: m.RoleId,
						MenuId: mm.MenuId,
						ApiKey: api.Key,
						Status: m.Status,
					})
				}
			}
			if err = s.roleRepo.CreateRoleMenus(ctx, roleMenus); err != nil {
				return err
			}
			if len(permissions) > 0 {
				return s.roleRepo.CreatePermissions(ctx, permissions)
			}
			return nil
		}
		return nil
	})
}

// Delete 删除角色
func (s *sysRoleService) Delete(ctx context.Context, roleId int64) error {
	//事物处理
	return s.tm.Transaction(ctx, func(ctx context.Context) error {
		if err := s.roleRepo.Delete(ctx, roleId); err != nil {
			return err
		}
		if err := s.roleRepo.DeleteRoleMenuByRoleId(ctx, roleId); err != nil {
			return err
		}
		if err := s.roleRepo.DeletePermissionByRoleId(ctx, roleId); err != nil {
			return err
		}
		return nil
	})
}
